package com.rtf.framework.common.config;

import com.google.common.collect.HashMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import lombok.Getter;
import lombok.Setter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.core.Ordered;

import java.util.Map;

/**
 * 系统属性
 * @Author : liupeng
 * @Date : 2019-01-12
 * @Modified By
 */
@ConfigurationProperties(prefix = "app")
@Setter
@Getter
public class AppProperties implements AppConstants {

    @Value("${spring.application.name:}")
    private String name;
    private String version = "v2.0";

    //是否开启session过滤登录
    private Boolean enableSessionFilter = false;

    //sso用户读取接口
    private String ssoQueryUserInfoPath = "127.0.0.1:8080/api/v2/user/queryUserInfo";
    // 错误页面路径，可以是绝对路径 或 当前项目下的路径
    private String errorPath = "/";

    // 全局参数
    private Map<String, Object> globalParams = Maps.newHashMap();

    private Session session = new Session();

    private ResponseConfig responseConfig = new ResponseConfig();

    private PageConfig pageConfig = new PageConfig();

    //异常信息配置
    private Exception exception = new Exception();

    // 是否mock用户
    private MockUser mockUser = new MockUser();

    /**
     * 获取当前应用运行的进程号，根据spring容器配置获取
     *
     * @return
     */
    public String getPid() {
        return System.getProperty("PID");
    }

    @Setter
    @Getter
    public static class MockUser {
        // 是否允许mock用户
        private Boolean enable = false;

        private String userId = "1";

        private String userName = "开发者";
    }

    @Setter
    @Getter
    public static class Session {

        //redis命名空间
        private String redisNamespace;

        //enableAnonSession 为true时，需要排除的URL（完整路劲，逗号分隔）
        private String specialAnonUrl;

        //不需要权限验证的URL，是否开启不获取Session
        private boolean enableAnonSession = false;

        /**
         * 是否开启开启session保存用户相关记录； 若要做单点登录、用户踢退等功能必须开启
         */
        private boolean enablePrincipalSession = true;

        // session加载策略，默认应用应启动时一直加载
        private String creationPolicy = "always";

        //session超时时间，单位秒，默认1800秒，即30分钟
        private int timeout = 1800;

        //session的更新时间间隔，5分钟，单位秒。默认不开启
        private int accessTimeUpdateInterval = 0;

        //cookie存储session id的key
        private String cookieKey = "_cs";

        //cookie所属的domain
        private String cookieDomain;

        //是否允许在cookie中保存sessionid
        private boolean cookieSessionWritable = true;

        //是否对cookie的session值进行加密，默认不加密；直接回写明文的cookie
        private boolean cookieSessionEncode = false;

        //请求header存储session id的key
        private String headerKey = "cs";

        //角色编码
        private String roleKey = "roles";

        //当前登录用户的id
        private String userIdKey = "userid";

    }

    @Setter
    @Getter
    public static class Exception {
        //打印异常栈信息
        private boolean printStackTrace = true;

        // 打印错误日志的最大行数
        private Integer maxNum = 10;

        public Integer getMaxNum() {
            return maxNum == null || maxNum < 0 ? 10 : maxNum;
        }

    }

    @Setter
    @Getter
    public static class PageConfig {

        //当前分页号，以1开始
        private String pageNum = "pagenum";

        //开始索引号
        private Boolean frontPageNumStartFromZero = true;

        //每页记录最大数
        private String pageSize = "pagesize";

        //每页实际记录数
        private String pageRealSize = "pagerealsize";

        //所有满足条件的记录数
        private String totalElements = "totalelements";

        //所有页数
        private String totalPages = "totalpages";
    }

    @Setter
    @Getter
    public static class ResponseConfig {
        private String successParamValue = "success";

        private String messageParam = "message";

        private String dataParam = "data";

        private String dataListParam = "datalist";

        private String codeParam = "code";

        private String exceptionIdParam = "exceptionid";

        private boolean supportJsonp = true;

        /**
         * 是否允许暴露datalist，允许：则分页参数结果和数组结果直接在{}中体现；否则在dataParam中体现。
         * 默认将datalist包含在data中，对于老的项目可以设置为true，将datalist、分页参数等暴露在一级json结果中。
         */
        private boolean enableExposeDatalist = false;

    }

    /**
     * 框架包目录
     */
    @Setter
    @Getter
    public static class AppPackage {

        public static final String BASE_PACKAGE = "com.rtf";

        public static final String[] BASE_PACKAGES = {BASE_PACKAGE, "com.lovol"};
    }

    @Setter
    @Getter
    public static class FilterOrder {
        //应用级别的filter，在session加载之前执行
        public static final int APP_FILTER = Ordered.HIGHEST_PRECEDENCE;

        //session filter，在app的fitler之后执行
        public static final int SESSION_FILTER = Ordered.HIGHEST_PRECEDENCE + 50;

        //安全filter，在session filter之后执行
        public static final int SECURE_FILTER = Ordered.HIGHEST_PRECEDENCE + 100;
    }

    /**
     * 配置文件执行顺序
     */
    @Setter
    @Getter
    public static class ConfigurationOrder {
        private static final Multimap<Integer, String> ConfigurationOrderMap = HashMultimap.create();

        //        初始化各个类的执行顺序
        {
            ConfigurationOrderMap.putAll(Ordered.HIGHEST_PRECEDENCE,
                    Lists.newArrayList("AppLoggingApplicationListener"));
            ConfigurationOrderMap.putAll(Ordered.HIGHEST_PRECEDENCE + 1,
                    Lists.newArrayList("AppDefaultConfigApplicationListener"));
        }

        /**
         * 获取默认的次序
         *
         * @param simpleClassName
         * @param defaultOrder
         * @return
         */
        public static int getOrder(String simpleClassName, int defaultOrder) {
            int targetOrder = defaultOrder;

            for (Integer order : ConfigurationOrderMap.keySet()) {
                if (ConfigurationOrderMap.get(order).contains(simpleClassName)) {
                    targetOrder = order;
                    break;
                }
            }

            return targetOrder;
        }
    }

}
